package org.plumecache.springboot.autoconfigurer;

import com.plumecache.core.CacheService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class CacheCommand {
    private String instanceName;
    private String command;
    private String key;
    private String field;
    private String value;

    private CacheService cacheInstance;

    public CacheService getCacheInstance() {
        return cacheInstance;
    }

    public void setCacheInstance(CacheService cacheInstance) {
        this.cacheInstance = cacheInstance;
    }

    public String getInstanceName() {
        return instanceName;
    }

    public void setInstanceName(String instanceName) {
        this.instanceName = instanceName;
    }

    public String getCommand() {
        return command;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String execute() {
        try {
            List<Object> parameters = getParameters();

            Optional<Method> first = Arrays.stream(cacheInstance.getClass().getMethods()).filter(r ->
                    r.getName().equals(this.command)
                            && r.getParameters().length == parameters.size()).findFirst();

            if (!first.isPresent()) {
                return String.format("not support method:%s", this.command);
            }

            Method method = first.get();
            Object invoke = method.invoke(cacheInstance, parameters.toArray());

            if ("void".equals(method.getReturnType().getTypeName())) {
                return "ok";
            }

            return String.valueOf(invoke);
        } catch (Exception e) {
            return ExceptionUtils.getStackTrace(e);
        }
    }

    private List<Object> getParameters() {
        List<Object> parameters = new ArrayList<>();
        if (StringUtils.isNotBlank(key)) {
            parameters.add(key);
        }

        if (StringUtils.isNotBlank(field)) {
            parameters.add(field);
        }

        if (StringUtils.isNotBlank(value)) {
            parameters.add(value);
        }

        return parameters;
    }

}
